﻿using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;

using DevExpress.XtraGrid;
using DevExpress.XtraGrid.Columns;
using DevExpress.XtraGrid.Views.Grid;

namespace CodeConvertServiceClient {
	public static class CFn {
		public const char CHAR_TAB = (char)9;

		public static void CopyToClipboard(string pStr) {
			if(!string.IsNullOrEmpty(pStr)) {
				Clipboard.SetText(pStr);
			}
		}

		/// <summary>
		/// Make Args Property
		/// </summary>
		public static string GenerateArgs(string pStr) {
            /* from CS
            public string argDataCompanyID;
             * to CS Args
            string _dataCompanyID;
            [DataMember]
            public string DataCompanyID {
                get {
                    return _dataCompanyID;
                }
                set {
                    _dataCompanyID = value;
                    OnPropertyChanged("DataCompanyID");
                }
            }*/
            IList<CSFieldValue> fields = CFn.GetFieldList(pStr);
			StringBuilder sb = new StringBuilder();
			sb.AppendLine(@"#region Field & Property");
			foreach(CSFieldValue field in fields) {
				sb.AppendLine(string.Format("{0} {1} = {2};", field.FieldType, field.FieldName, (field.FieldType == "string" ? "\"\"" : (field.FieldType == "bool" ? "false" : (field.FieldType == "long" || field.FieldType == "double" ? "0" : "")))));

				sb.AppendLine(string.Format("{0}", "[DataMember]"));
				sb.AppendLine(string.Format("public {0} {1}", field.FieldType, field.PropertyName) + @" {");
				sb.AppendLine(string.Format("{0}get", CHAR_TAB) + @" {");
				sb.AppendLine(string.Format("{0}{0}return {1};", CHAR_TAB, field.FieldName));
				sb.AppendLine(string.Format("{0}", CHAR_TAB) + @"}");
				sb.AppendLine(string.Format("{0}set", CHAR_TAB) + @" {");
				sb.AppendLine(string.Format("{0}{0}{1} = value;", CHAR_TAB, field.FieldName));
				sb.AppendLine(string.Format("{0}{0}OnPropertyChanged(\"{1}\");", CHAR_TAB, field.PropertyName));
				sb.AppendLine(string.Format("{0}", CHAR_TAB) + @"}");
				sb.AppendLine("}");
			}
			sb.AppendLine(@"#endregion");
			return sb.ToString();
		}


		/// <summary>
		/// Make Args Property
		/// </summary>
		public static string GenerateEntity(string pStr) {
			/* from CS
			Fields.Add "custname"
			 * to CS Entity
			public string Custname { get; set; }
			*/

			IList<string> lines = new List<string>();
			foreach(string str in pStr.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries)) {
				if(!string.IsNullOrEmpty(str.Trim())) {
					string[] strings = str.Trim().Split(new[] { "\"" }, StringSplitOptions.RemoveEmptyEntries);
					if(strings.Length == 2) {
						lines.Add(string.Format("public string {0} {{ get; set; }}", CFn.FormatPascalCase(strings[1])));
					}
				}
			}

			StringBuilder sb = new StringBuilder();
			sb.AppendLine(@"#region VB Field");
			foreach(string line in lines) {
				sb.AppendLine(line);
			}
			sb.AppendLine(@"#endregion");
			return sb.ToString();
		}

		/// <summary>
		/// 허용 확장자
		/// </summary>
		static readonly string[] _REPORT_XML_EXT = new[] { ".RPX"/*, ".REPX", ".XML"*/ };
		public static bool CheckReportXml(IDataObject data, ref string fPath) {

			#region

			/*if(formats != null && formats.Length > 0) {
				//				System.Diagnostics.Debug.WriteLine(e.Data);
				if(formats[0].Equals("Shell IDList Array")) {
					//    [0]: "Shell IDList Array"
					//    [1]: "UsingDefaultDragImage"
					//    [2]: "DragImageBits"
					//    [3]: "DragContext"
					//    [4]: "DragSourceHelperFlags"
					//    [5]: "InShellDragLoop"
					//    [6]: "FileDrop"
					//    [7]: "FileNameW"
					//    [8]: "FileName"
					//    [9]: "IsShowingLayered"
					//    [10]: "DragWindow"
					//    [11]: "IsComputingImage"
					//    [12]: "DropDescription"
					//    [13]: "DisableDragText"
					//    [14]: "IsShowingText"
					//    [15]: "ComputedDragImage"
					if(e.Data.GetDataPresent("FileName")) {
						//						e.Data.GetData("FileName")
					}
				}
			}*/

			#endregion

			if(data.GetDataPresent("FileName")) {
				if(data.GetData("FileName") is string[]) {
					string[] arr = (string[])data.GetData("FileName");
					if(arr != null && arr.Length > 0) {
						if(_REPORT_XML_EXT.Contains(Path.GetExtension(arr[0].ToUpper()))) {
							fPath = arr[0];
							return true;
						}
					}
				}
			}
			return false;
		}


		public static string ConvertUnitActiveReportToXtraReport(object pdd) {
			//			return System.Convert.ToDouble(pdd ?? 0) / 1440 * 100;
			return string.Format("{0}({1:0.###})", pdd, System.Convert.ToDouble(pdd ?? 0) / 1440 * 100);
		}

		public static string ReportXmlParse(string fPath, GridControl gridControl1, GridView gridView1, Button sender = null) {
			if(!File.Exists(fPath)) {
				MessageBox.Show("파일이 존재하지 않습니다.");
				return "";
			}
			string buttonText = "";
			if(sender != null) {
				buttonText = sender.Text;
				sender.Text = "waiting...";
				sender.Enabled = false;
			}
			StringBuilder sb = new StringBuilder();
			try {
				DataSet ds = new DataSet();
				ds.ReadXml(new XmlTextReader(fPath), XmlReadMode.Auto);

				#region ActiveReportsLayout

				DataTable dtActiveReportsLayout = ds.Tables["ActiveReportsLayout"];
				if(dtActiveReportsLayout != null && dtActiveReportsLayout.Rows.Count > 0) {
					sb.AppendLine("<<<PrintWidth>>>");
					sb.AppendLine(string.Format("{0}", ConvertUnitActiveReportToXtraReport(dtActiveReportsLayout.Rows[0]["PrintWidth"])));
				}

				#endregion


				#region PageSettings

				DataTable dtPageSettings = ds.Tables["PageSettings"];
				if(dtPageSettings != null && dtPageSettings.Rows.Count > 0) {
					sb.AppendLine("<<<PageSettings>>>");
					for(int k = 0 ; k < dtPageSettings.Columns.Count - 1 ; k++) {
						sb.AppendLine(string.Format("{0}:{1}"
							, dtPageSettings.Columns[k].ColumnName, ConvertUnitActiveReportToXtraReport(dtPageSettings.Rows[0][k])));
					}
				}

				#endregion


				#region Section

				DataTable dtSection = ds.Tables["Section"];
				if(dtSection != null) {
					if(dtSection.Rows.Count > 0) {
						sb.AppendLine("<<<Section List>>>");
					}
					foreach(DataRow dataRow in dtSection.Rows) {
						sb.AppendLine(string.Format("{0}:{1}", dataRow["Name"], ConvertUnitActiveReportToXtraReport(dataRow["Height"])));
					}
				}

				#endregion


				#region Control

				DataTable dtControl = ds.Tables["Control"];
				if(dtSection != null) {
					int idx = 0;
					dtControl.Columns["Section_Id"].SetOrdinal(idx++);

					dtControl.Columns["Type"].SetOrdinal(idx++);

					dtControl.Columns["Name"].SetOrdinal(idx++);

					try {
						if(!dtControl.Columns.Contains("OutputFormat")) {
							dtControl.Columns.Add("OutputFormat");
						}
					} catch {
					}
					dtControl.Columns["OutputFormat"].SetOrdinal(idx++);

					if(!dtControl.Columns.Contains("DataField")) {
						dtControl.Columns.Add("DataField");
					}
					dtControl.Columns["DataField"].SetOrdinal(idx++);

					if(!dtControl.Columns.Contains("Caption")) {
						dtControl.Columns.Add("Caption");
					}
					dtControl.Columns["Caption"].SetOrdinal(idx++);

					if(!dtControl.Columns.Contains("Text")) {
						dtControl.Columns.Add("Text");
					}
					dtControl.Columns["Text"].SetOrdinal(idx++);

					if(!dtControl.Columns.Contains("Control_Text")) {
						dtControl.Columns.Add("Control_Text");
					}
					dtControl.Columns["Control_Text"].SetOrdinal(idx++);

					gridView1.Columns.Clear();
					gridControl1.DataSource = dtControl;
					//gridView1.Columns[0].Group();
					//gridView1.ExpandAllGroups();
					//			gridView1.ApplyFindFilter(" OutputFormat is not null");

					if(gridView1.Columns.Count > idx) {
						foreach(GridColumn column in gridView1.Columns) {
							if(column.AbsoluteIndex >= idx - 1) {
								column.Visible = false;
							}
						}
					}


					gridView1.Columns["Name"].SortIndex = 0;
					gridView1.Columns["OutputFormat"].FilterInfo = new ColumnFilterInfo("Not IsNullOrEmpty([OutputFormat])");
				}
				#endregion

				//gridView1.Columns["OutputFormat"].FilterInfo = new ColumnFilterInfo();
				//gridView1.ApplyColumnsFilter();
				/*DataView dv = dtControl.DefaultView;
			if(dtControl.Columns.Contains("OutputFormat")) {
				dv.RowFilter = " OutputFormat is not null";
			}

			gridControl1.DataSource = dv;*/
			} catch(Exception ex) {
				MessageBox.Show(ex.ToString());
			}
			if(sender != null) {
				sender.Text = buttonText;
				sender.Enabled = true;
			}

			return sb.ToString();
		}

		public static string EntityCompare(string pIn, string pOut) {
			IList<CSFieldValue> fieldsIn = CFn.GetFieldList(pIn);
			IList<CSFieldValue> fieldsOut = CFn.GetFieldList(pOut);
			StringBuilder sb = new StringBuilder();
			bool flagSame = false;
			foreach(CSFieldValue field in fieldsOut) {
				// 대소문자 구분없이 동일한 필드명이 있는지 확인
				flagSame = (fieldsIn.Count(inV => inV.FieldNameOriginal.ToUpper() == field.FieldNameOriginal.ToUpper()) != 0);
				sb.AppendLine(string.Format("{0}public {1} {2}", flagSame ? "//" : "", field.FieldType, field.FieldNameOriginal) + " { get; set; }");
			}
			return sb.ToString();
		}

		public static string SQLOutputToEntityProperty(string input) {
			/*
			[from VB]
			h.F_ID as FID, F_Shipper, F_Notify, F_Consignee, F_Description, F_MarkPKG, F_MarkGross
			 [to New SQL & CS Source]
			h.F_ID as FID, F_Shipper as Shipper, F_Notify as Notify, F_Consignee as Consignee, F_Description as Description, F_MarkPKG as MarkPKG, F_MarkGross as MarkGross
			public string FID { get; set; }
			public string Shipper { get; set; }
			 * 
			 * 
			*/
			string field = "";
			int idx = -1;
			IList<SQLFieldValue> fields = new List<SQLFieldValue>();
			foreach(string str in input.Replace("\r", "").Replace("\n", "").Replace("\t", "").Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries)) {
				// 줄바꿈, 개행, 탭문자 제거후 Split
				field = str.Trim().ToUpper();// 공백 제거 및 대문자로 변경
				if(field != "") {
					SQLFieldValue sqlfield = new SQLFieldValue() {
						FieldStr = field
					};

					// 콤마(.)까지 제외, Table Alias 추출
					idx = field.IndexOf(".");
					if(idx != -1) {
						sqlfield.TableAlias = field.Substring(0, idx).Trim();
						field = field.Substring(idx + 1);
					}

					// FieldNameOri, Field Alias 추출 ( 기존에 있는 경우 Alias 명칭 그대로 유지. 단, 맨 앞 "F_" 는 제외 )
					idx = field.IndexOf(" AS "/*, StringComparison.OrdinalIgnoreCase*/);
					if(idx != -1) {
						sqlfield.FieldNameOri = field.Substring(0, idx).Trim();

                        // "F_" 제외
					    string fieldAliasNew = field.Substring(idx + 4).Trim();
                        if(fieldAliasNew.StartsWith("F_")) {
                            sqlfield.FieldAlias = fieldAliasNew.Substring(2);
                        } else {
                            sqlfield.FieldAlias = fieldAliasNew;
                        }
					} else {
						sqlfield.FieldNameOri = field.Trim();

						// "F_" 제외
						if(sqlfield.FieldNameNew.StartsWith("F_"/*, StringComparison.OrdinalIgnoreCase*/)) {
							sqlfield.FieldAlias = sqlfield.FieldNameNew.Substring(2);
						} else {
							sqlfield.FieldAlias = sqlfield.FieldNameNew;
						}
					}
					fields.Add(sqlfield);
				}
			}
			StringBuilder sb = new StringBuilder();
			string sql = "";
			sql = fields.Aggregate(sql, (current, item) => current + string.Format(", {0}", item.SqlOutResult));
			if(fields.Count > 0) {
				sql = sql.Substring(2);// 맨 앞 ", " 제거
			}
			sb.AppendLine(@"/*============ SQL Output New ======== */");
			sb.AppendLine(sql);
			sb.AppendLine(@"/*============ CS Property ======== */");
			foreach(SQLFieldValue item in fields) {
				//				sb.AppendLine(string.Format("public string {0} {1}", item.FieldNameNew, "{ get; set; }"));
				sb.AppendLine(string.Format("public string {0} {1}", item.FieldAlias, "{ get; set; }"));
			}
			return sb.ToString();
		}

		public static string FormatPascalCase(string str) {
			StringBuilder sb = new StringBuilder(str.Length);

			if(string.IsNullOrEmpty(str)) {
				return str;
			}

			if(str.Length < 2) {
				return str.ToUpper();
			}

			// Split the string into words.
			string[] words = str.Split(new char[] { }, StringSplitOptions.RemoveEmptyEntries);

			foreach(string word in words) {
				sb.AppendFormat("{0}{1}", word.Substring(0, 1).ToUpper(), word.Substring(1));
			}

			return sb.ToString();
		}


		/// <summary>
		/// <b>■ 필드 목록 파싱</b>
		/// <br/>- Creator : Jaeyong Park NOTE Summary
		/// <br/>- First Crate Date : 2012-01-06
		/// <br/>- Last Modifier : Jaeyong Park
		/// <br/>- Last Modify Date : 2012-01-06
		/// <br/>from CS Source
		/// <br/>public string argDataCompanyID;
		/// <br/>public string argDataCompanyName;
        /// <br/>public string test1 = "";
		/// </summary>
		public static IList<CSFieldValue> GetFieldList(string input) {
			IList<CSFieldValue> fields = new List<CSFieldValue>();
			string line = "";
			foreach(string str in input.Split(new[] {
				Environment.NewLine
			}, StringSplitOptions.RemoveEmptyEntries)) {
				if(!string.IsNullOrEmpty(str)) {
                    // public, 탭문자 제거
					line = str.Trim(';').Replace("public ", "").Replace("\t", "");
                    // 공백으로 Split
					string[] item = line.Split(new string[] {
						" "
					}, StringSplitOptions.RemoveEmptyEntries);
                    // CSFieldValue 생성
					if(item.Length > 1) {
						fields.Add(new CSFieldValue(item[0], item[1].StartsWith("arg", StringComparison.OrdinalIgnoreCase) ? item[1].Substring(3) : item[1]));// arg 제거
					}
				}
			}
			return fields;
		}
	}

	public class CSFieldValue {
		private string _fieldType = "";
		public string FieldType {
			get {
				return _fieldType;
			}
			set {
				_fieldType = value;
			}
		}
		private string _fieldNameOriginal = "";
		/// <summary>
		/// arg 를 포함한 원래 필드명
		/// </summary>
		public string FieldNameOriginal {
			get {
				return _fieldNameOriginal;
			}
			set {
				_fieldNameOriginal = value;
			}
		}

		/// <summary>
		/// FieldNameOriginal 에 서 첫 글자 소문자 처리하고 "_" 을 맨 앞에 붙임
		/// </summary>
		public string FieldName {
			get {
				if(!string.IsNullOrEmpty(_fieldNameOriginal)) {
					Char firstChart = _fieldNameOriginal.ToCharArray()[0];
					return _fieldNameOriginal.Remove(0, 1).Insert(0, "_" + firstChart.ToString().ToLower());
				}
				return _fieldNameOriginal;
			}
		}
		/// <summary>
		/// FieldNameOriginal 에 서 첫 글자 대문자 처리
		/// </summary>
		public string PropertyName {
			get {
				if(!string.IsNullOrEmpty(_fieldNameOriginal)) {
					Char firstChart = _fieldNameOriginal.ToCharArray()[0];
					return _fieldNameOriginal.Remove(0, 1).Insert(0, firstChart.ToString().ToUpper());
				}
				return _fieldNameOriginal;
			}
		}


		public CSFieldValue(string fieldType, string fieldNameOriginal) {
			_fieldType = fieldType;
			_fieldNameOriginal = fieldNameOriginal;
		}
	}

	public class SQLFieldValue {
		/// <summary>
		/// Table Alise & . & F_ 를 모두 포함한 원본 필드 하나의 문자열
		/// </summary>
		public string FieldStr {
			get;
			set;
		}
		/// <summary>
		/// Table Alias
		/// <br/>h.f_id => h
		/// </summary>
		public string TableAlias {
			get;
			set;
		}
		/// <summary>
		/// Field Alias
		/// <br/>h.f_id as fid => fid
		/// </summary>
		public string FieldAlias {
			get;
			set;
		}
		/// <summary>
		/// Table Alise & . & Field Alias 를 제외한 원본 필드명
		/// </summary>
		public string FieldNameOri {
			get;
			set;
		}
		/// <summary>
		///FieldNameOri 에서 "F_" 를 제외한 필드명
		/// </summary>
		public string FieldNameNew {
			get {
				if(FieldNameOri.StartsWith("F_"/*, StringComparison.OrdinalIgnoreCase*/)) {
					return FieldNameOri.Substring(2);
				}
				return FieldNameOri;
			}
		}
		public string SqlOutResult {
			get {
				return string.Format("{0}{1} AS {2}", !string.IsNullOrEmpty(TableAlias) ? (TableAlias + ".") : "", FieldNameOri, FieldAlias);
			}
		}
	}
}
